package session

import (
	"gitee.com/zhendliu/sorm/clause"
	"gitee.com/zhendliu/sorm/parser"
	"github.com/pkg/errors"
	"strings"
)

func (s *Session) Update(desc string, args ...interface{}) (int64, error) {
	defer s.Clear()

	tableNames, err := s.getTableNamesForUpdate()
	if err != nil {
		return 0, err
	}

	var row int64 = 0
	for _, tnameOwner := range tableNames {
		r, err := s.updateTable(tnameOwner, desc, args...)
		if err != nil {
			return 0, err
		}
		row += r
	}

	return row, nil
}

func (s *Session) getTableNames() ([]string, error) {
	var (
		tableNames []string
		err        error
	)
	table := s.RefTable()

	if table.SubTableFile != "" {
		whereExp, values := s.clause.Get(clause.WHERE)
		if strings.Contains(whereExp, table.SubTableFile) {
			timeIndex := strings.Index(whereExp, table.SubTableFile)
			questionMarks := strings.Count(whereExp[:timeIndex], "?")
			if questionMarks > len(values) {
				return nil, errors.New("获取表名失败")
			}
			tableName, err := s.GetTableFromTableAndSplitFiled(table.Name, values[questionMarks])
			if err != nil {
				return nil, errors.New("获取表名失败")
			}
			tableNames = append(tableNames, tableName)
		} else {
			tableNames, err = s.GetTableFromNone(table.Name)
			if err != nil {
				return nil, errors.Wrap(err, "分表的策略不支持")
			}
		}
	} else {
		tableNames = append(tableNames, table.Name)
	}

	return tableNames, nil
}

func (s *Session) getTableNamesForUpdate() ([]string, error) {
	var (
		tableNames []string
	)
	table := s.RefTable()

	if table.SubTableFile != "" {
		whereExp, values := s.clause.Get(clause.WHERE)
		if strings.Contains(whereExp, table.SubTableFile) {
			timeIndex := strings.Index(whereExp, table.SubTableFile)
			questionMarks := strings.Count(whereExp[:timeIndex], "?")
			if questionMarks > len(values) {
				return nil, errors.New("获取表名失败")
			}
			tableName, err := s.GetTableFromTableAndSplitFiled(table.Name, values[questionMarks])
			if err != nil {
				return nil, errors.New("获取表名失败")
			}
			tableNames = append(tableNames, tableName)
		} else {
			return nil, errors.New("更新条件写，分表的情况下,条件一定要包含分表字段")
		}
	} else {
		tableNames = append(tableNames, table.Name)
	}

	return tableNames, nil
}

func (s *Session) updateTable(tableName string, desc string, args ...interface{}) (int64, error) {
	//table := s.RefTable()
	tname := parser.GetTableName(tableName)
	db, ok := s.dbs[tname]
	if !ok { // 如果没有找到，就说明没有分表，就用默认的db
		db = s.db
	}

	vals := []interface{}{tableName, desc}
	vals = append(vals, args...)
	s.clause.Set(clause.UPDATE, vals...)
	sql, vars := s.clause.Build(clause.UPDATE, clause.WHERE)

	result, err := s.exec(s.ctx, db.Db, db.Dia, sql, vars)
	if err != nil {
		return 0, errors.Wrapf(err, "更新 %s 表失败", tableName)
	}

	row, _ := result.RowsAffected()

	return row, nil
}

/*// Update records with where clause
// support map[string]interface{}
// also support kv list: "Name", "Tom", "Age", 18, ....
func (s *Session) Update(desc string, args ...interface{}) (int64, error) {
	defer s.Clear()
	var (
		tableNames []string
		err        error
		vals       []interface{}
		resultList []sql.Result
	)

	table := s.RefTable()

	if table.SubTableFile != "" {
		whereExp, values := s.clause.Get(clause.WHERE)
		if strings.Contains(whereExp, table.SubTableFile) {
			timeIndex := strings.Index(whereExp, table.SubTableFile)
			questionMarks := strings.Count(whereExp[:timeIndex], "?")
			if questionMarks > len(values) {
				return 0, errors.New("获取表名失败")
			}

			tableName, err := s.GetTableFromTableAndSplitFiled(table.Name, values[questionMarks])
			if err != nil {
				return 0, errors.New("获取表名失败")
			}
			tableNames = append(tableNames, tableName)
		} else {
			// 如果没有,包含则要加载全部的表名,仅支持取模的方式
			tableNames, err = s.GetTableFromNone(table.Name)
			if err != nil {
				return 0, errors.Wrap(err, "分表的策略不支持")
			}
		}
	} else {
		tableNames = append(tableNames, table.Name)
	}

	for _, tnameOwner := range tableNames {
		tname := parser.GetTableName(tnameOwner)
		db, ok := s.dbs[tname]
		if !ok { // 如果没有找到，就说明没有分表，就用默认的db
			db = s.db
		}

		s.clause.Set(clause.UPDATE, append(append(vals, s.RefTable().Name, desc), args...)...)
		sql, vars := s.clause.Build(clause.UPDATE, clause.WHERE)

		result, err := s.Exec(s.ctx, db.Db, sql, vars)
		if err != nil {
			return 0, errors.Wrap(err, "更新失败")
		}
		resultList = append(resultList, result)
	}

	if len(resultList) == 0 {
		return 0, errors.Wrap(err, "更新失败")
	}
	var row int64 = 0
	for i := range resultList {
		r, _ := resultList[i].RowsAffected()
		row += r
	}
	return row, nil
}*/
